/**
 * Copyright (c) 2008, Keisuke Inoue, Syracuse Unviersity
 * All rights reserved.
 *
 */
package edu.syr.iis.web.model;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;

import edu.syr.iis.web.util.HibernateUtil;

/**
 * @author kinoue
 *
 */
public class DialogueActLabelManager
{

	/**
	 * Returns list of all DialogueActLabels of the specified DialogueActScheme sorted by dialogueActLabelId
	 */
	public List<DialogueActLabel> getDialogueActLabelsByScheme(DialogueActScheme dialogueActScheme)
	{
		return getDialogueActLabelsByScheme(dialogueActScheme, true);
	}

	public List<DialogueActLabel> getDialogueActLabelsByScheme(DialogueActScheme dialogueActScheme, boolean lazy)
	{
		List<DialogueActLabel> list = null;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		try
		{
			Criteria criteria = session.createCriteria(DialogueActLabel.class);

			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(DialogueActDimension.class);	    
			detachedCriteria.add(Property.forName("dialogueActScheme").eq(dialogueActScheme));

			criteria.add(Restrictions.in("dialogueActDimension", detachedCriteria.getExecutableCriteria(session).list()));
			criteria.addOrder(Order.asc("dialogueActDimension.dialogueActDimensionId"));
			criteria.addOrder(Order.asc("label"));
			
			if (!lazy) 
			{
				criteria.setFetchMode("dialogueActDimension", FetchMode.JOIN);
				criteria.setFetchMode("dialogueActDimension.dialogueActScheme", FetchMode.JOIN);
			}
			
			list = criteria.list();
 			
			// This will force the inner-join fetch mode for messages and function/domain
			// (I don't know any other ways to do this.)
			// So that the viewer (.jsp) can access to the fields after the session is closed.
			//
			if (!lazy) 
			{
				for (DialogueActLabel dal: list) 
				{
					dal.getNumLabeled();
					dal.getDialogueActNum();
				}
			}
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
		return list;
	}
	
	

	/**
	 * Returns list of all DialogueActLabels of the specified DialogueActDimension sorted by dialogueActLabelId
	 */
	public List<DialogueActLabel> getDialogueActLabels(DialogueActDimension dialogueActDimension)
	{
		List<DialogueActLabel> list = null;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		try
		{
			String query = "FROM DialogueActLabel WHERE dialogueActDimensionId = ?";
			list = session.createQuery(query).setInteger(0, dialogueActDimension.getDialogueActDimensionId()).list();

			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
		return list;
	}

	public List<DialogueActLabel> getDialogueActLabels()
	{
		return getDialogueActLabels(true);
	}
	
	public List<DialogueActLabel> getDialogueActLabels(boolean lazy)
	{
		return getDialogueActLabels(null, lazy);
	}
	
	public List<DialogueActLabel> getDialogueActLabels(DialogueActDimension dialogueActDimension, boolean lazy)
	{
		List<DialogueActLabel> list = null;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		try
		{
			DetachedCriteria detachedCriteria = DetachedCriteria.forClass(DialogueActScheme.class)
				.addOrder(Order.asc("dialogueActShemeId"));
			
			Criteria criteria = session.createCriteria(DialogueActLabel.class)
			// .addOrder(Order.asc("dialogueActDimension.dialogueActScheme.dialogueActSchemeId"))
			.addOrder(Order.asc("dialogueActDimension.dialogueActDimensionId"))
			.addOrder(Order.asc("label"));
			
			if (dialogueActDimension != null)
				criteria.add(Restrictions.eq("dialogueActDimension", dialogueActDimension));
			
			if (!lazy) 
			{
				criteria.setFetchMode("dialogueActDimension", FetchMode.JOIN);
				criteria.setFetchMode("dialogueActDimension.dialogueActScheme", FetchMode.JOIN);
			}
			
			list = criteria.list();
			
			if (!lazy)
			{
				for (DialogueActLabel dal: list)
				{						
						dal.getNumLabeled();
						dal.getDialogueActNum();
				}
				
			}
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
		return list;
	}



	/**
	 * Returns list of all the DialogueActLabels with the given Scheme and Dimension 
	 * @param dimension 
	 * @param scheme 
	 */
	public List<DialogueActLabel> getDialogueActLabelsBySchemeAndDimension(String scheme, String dimension)
	{
		List<DialogueActLabel> list = null;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		try
		{
			String query = "FROM DialogueActLabel " +
			"  WHERE dialogueActDimension.dialogueActScheme.scheme = ? and dialogueActDimension.dimension = ?" +
			"  ORDER BY label";

			list = session.createQuery(query).setString(0, scheme).setString(1, dimension).list();
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
		return list;
	}




	public DialogueActLabel getDialogueActLabel(int id, boolean lazy)
	{
		DialogueActLabel dialogueActLabel = null;
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();

		try
		{
			Criteria criteria = session.createCriteria(DialogueActLabel.class)
				.add(Restrictions.eq("dialogueActLabelId", id));
			
			if (!lazy)
			{
				criteria.setFetchMode("dialogueActDimension", FetchMode.JOIN);
				criteria.setFetchMode("dialogueActDimension.dialogueActScheme", FetchMode.JOIN);				
			}
			
			dialogueActLabel = (DialogueActLabel) criteria.uniqueResult();
			
			if (!lazy) 
			{
				dialogueActLabel.getMessages().size();
				dialogueActLabel.getFunctionDialogueActs().size();
				dialogueActLabel.getDomainDialogueActs().size();				
			}
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
		return dialogueActLabel;
	}


	public DialogueActLabel getDialogueActLabel(int dialogueActLabelId)
	{
		return getDialogueActLabel(dialogueActLabelId, true);
	}

	/**
	 * Saves a DialogueActLabel object.
	 */
	public void saveDialogueActLabel(DialogueActLabel dialogueActLabel)
	{
		Session session = HibernateUtil.getSessionFactory()
		.getCurrentSession();
		session.beginTransaction();
		try
		{
			session.saveOrUpdate(dialogueActLabel);
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
	}
	
	public String testToString()
	{
		return new String("Ho ho ho!");
	}

	/**
	 * Deletes DialogueActLabel record with matching dialogueActLabelId 
	 */
	public void deleteDialogueActLabel(int dialogueActLabelId)
	{
		Session session = 
			HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();	
		try
		{
			Object toDelete = session.get(DialogueActLabel.class,new Integer(dialogueActLabelId));

			if (toDelete != null) { 
				session.delete(toDelete);
			}

			session.flush();
			session.getTransaction().commit();
		}
		catch (HibernateException e)
		{
			session.getTransaction().rollback();
			throw e;
		}
	}


}
